package org.dlow.config;

import org.springframework.context.annotation.Import;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @EnableProviderRpc - 启用RPC服务端功能
 * 
 * <p>该注解用于在SpringBoot应用的启动类上,启用RPC服务端功能。
 * 通过@Import导入ProviderConfig配置类,自动配置RPC服务端所需的组件。
 * 
 * <h3>核心功能:</h3>
 * <ul>
 *   <li>自动导入ProviderConfig配置类</li>
 *   <li>注册ProviderPostProcessor后置处理器</li>
 *   <li>初始化服务端相关组件(注册中心、调用器、过滤器等)</li>
 *   <li>启动Netty服务端,监听客户端请求</li>
 *   <li>扫描并注册所有带@RpcService注解的服务</li>
 * </ul>
 * 
 * <h3>使用示例:</h3>
 * <pre>
 * &#64;SpringBootApplication
 * &#64;EnableProviderRpc  // 添加此注解启用RPC服务端
 * public class ProviderApplication {
 *     public static void main(String[] args) {
 *         SpringApplication.run(ProviderApplication.class, args);
 *     }
 * }
 * </pre>
 * 
 * <h3>工作原理:</h3>
 * <ol>
 *   <li>SpringBoot启动时解析@EnableProviderRpc注解</li>
 *   <li>通过@Import导入ProviderConfig配置类</li>
 *   <li>ProviderConfig创建并注册ProviderPostProcessor到Spring容器</li>
 *   <li>ProviderPostProcessor作为BeanPostProcessor,扫描所有Bean</li>
 *   <li>发现带有@RpcService注解的Bean,将服务注册到注册中心</li>
 *   <li>单独启动守护线程运行Netty服务端,监听指定端口</li>
 *   <li>客户端请求到达时,从缓存中获取服务实例并执行方法</li>
 * </ol>
 * 
 * <h3>配置要求:</h3>
 * <p>需要在application.yml中配置RPC相关参数:
 * <pre>
 * rpc:
 *   port: 9090              # 服务端监听端口
 *   serialization: jdk      # 序列化方式
 *   invoke: jdk             # 方法调用方式(反射)
 *   corePollSize: 5         # 线程池核心线程数
 *   maximumPoolSize: 10     # 线程池最大线程数
 *   registry:
 *     name: zookeeper       # 注册中心类型
 *     address: 127.0.0.1:2181  # 注册中心地址
 * </pre>
 * 
 * <h3>线程模型:</h3>
 * <p>Netty服务端运行在守护线程中(daemon thread),采用solo方式启动:
 * <ul>
 *   <li>不会阻塞SpringBoot主线程的启动</li>
 *   <li>当主线程退出时,守护线程会自动退出</li>
 *   <li>保证服务端可以持续监听客户端请求</li>
 * </ul>
 * 
 * @description: 启用RPC服务端功能的注解
 * @Author: 山沐与山
 * @CreateTime: 2024-05-17 14:55
 * @see ProviderConfig 服务端配置类
 * @see ProviderPostProcessor 服务端后置处理器
 * @see RpcService 服务发布注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(ProviderConfig.class)
public @interface EnableProviderRpc {
}
